/*******************************************************************************
 * Copyright (c) 2012, 2013 XML-Print Project.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     XML-Print Project - initial API and implementation
 ******************************************************************************/
package info.xmlprint.core.mapping;

import info.xmlprint.core.format.Format;
import info.xmlprint.core.format.FormatGroup;
import info.xmlprint.core.innerlink.BaseItem;
import info.xmlprint.core.innerlink.InnerLink;
import info.xmlprint.core.innerlink.InnerLinkGroup;
import info.xmlprint.core.referencesystem.PageMasterGroup;
import info.xmlprint.core.project.PrintProject;
import info.xmlprint.core.referencesystem.AbstractBaseItem;
import info.xmlprint.core.referencesystem.PageMaster;
import info.xmlprint.core.referencesystem.ReferenceFieldGroup;
import info.xmlprint.core.referencesystem.ReferencingSystemGroup;
import info.xmlprint.core.xml.PElement;
import info.xmlprint.run.Configuration;
import info.xmlprint.run.Constants;
import info.xmlprint.run.RuntimeUtil;
import info.xmlprint.ui.message.GuiMessages;
import info.xmlprint.ui.widgets.IGroup;
import info.xmlprint.util.FileUtil;
import info.xmlprint.util.XmlUtil;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.QName;
import org.dom4j.io.SAXReader;
import org.eclipse.jface.dialogs.MessageDialog;

/*
 * style (Zuordnungen von Elemente und Formate) 
 * als xml/xsl erzeugen, speichern, importieren usw.
 */
public class MappingGroup implements Serializable, IGroup {
	/**
	 * 
	 */
	private static final long serialVersionUID = 2812912132570695523L;

	//private PageMasterGroup pageMasterGroup;

	private FormatGroup formatGroup;
	//private PageMaster pageMaster;
	private String oldPM = "standard";
	private boolean newPM = false;

	private List<Mapping> mappingList = new ArrayList<Mapping>();

	private static Logger logger = Logger.getLogger(MappingGroup.class
			.toString());

	public static int getGroupIndexOf(String str, char[] group) {
		for (int i = 0; i < str.length(); i++) {
			for (char c : group) {
				if (str.charAt(i) == c) {
					return i;
				}
			}
		}
		return -1;
	}

	public static void main(String args[]) {
		MappingGroup mp = new MappingGroup();
		// mp.readXmlFile("e://a.xml");
		System.out.println(mp
				.getRSFOText("A-${Lied}$Strophe.${nbspace}${linenumber}"));
	}

	// private boolean isSorted = false;

	private String mainNamespacePrefix;

	private String mainNamespaceUri;;

	private int templateCounter = 0;

	public MappingGroup() {
		//pageMaster = new PageMaster();
	}

	public void add(Mapping mp) {
		this.mappingList.add(mp);
	}

	public boolean containsEmptyFormat() {
		for (Mapping mp : mappingList) {
			Format f = formatGroup.getFormatByName(mp.getFormatName());
			try {
				f.getName();
			} catch (NullPointerException ne) {
				return true;
			}
		}
		return false;
	}

	public FormatGroup getFormatGroup() {
		return formatGroup;
	}

	/*
	public PageMaster getPageMaster() {
		return pageMaster;
	}*/

	public List<Mapping> getList() {
		// if (!isSorted) {
		// Collections.sort(mappingList, new Comparator<Mapping>() {
		// public int compare(Mapping arg0, Mapping arg1) {
		// return arg0.getName().compareTo(arg1.getName());
		// }
		// });
		// isSorted = true;
		// }
		return this.mappingList;
	}

	public String getMainNamespacePrefix() {
		return mainNamespacePrefix;
	}

	public String getMainNamespaceUri() {
		return mainNamespaceUri;
	}

	public Mapping getMappingByName(String name) {
		for (Mapping m : mappingList) {
			if (m.getName().equals(name))
				return m;
		}
		return null;
	}

	public List<Mapping> getMappingsByName(String name) {
		ArrayList<Mapping> list = new ArrayList<Mapping>();
		if (name != null)
			for (Mapping m : mappingList) {
				if (m.getName().equals(name))
					list.add(m);
			}

		if (list.size() > 0)
			return list;

		return null;

	}

//	public void getFOConfigFile() {
//		Format format = RuntimeUtil.getInstance().getCurrentPrintProject().get
//		String fn_seprule_bool = format.getFootnoteAttribute("fn-seprule-bool");
//		String fn_seprule_width = format.getFootnoteAttribute("fn-seprule-width");
//		String fn_seprule_width_long = format.getFootnoteAttribute("fn-seprule-width-long");
//		String fn_seprule_thickness = format.getFootnoteAttribute("fn-seprule-thickness");
//		String fn_seprule_color = format.getFootnoteAttribute("fn-seprule-color");
//		String fn_seperator_mult = format.getFootnoteAttribute("fn-separator-mult");
//		
//		if (FoConfiguration.getInstance().getEngineName()
//				.equalsIgnoreCase("XML-Print")) {
//			fo.addAttribute("place", format.getId());
//			// fo.addAttribute("fn-id", "1");
//			if (fn_type.equalsIgnoreCase("Endnote")) {
//				fo.addAttribute("fn-type", "endnote");
//			}
//		}
//		
//	}
	
	public String getRSFOText(String s) {
		int next_punct;
		int next_variable;
		int next_rightBrace;

		char[] punct = { '.', ',', ';', ':', '-', '&' };

		String output = "";

		while (!s.isEmpty()) {
			if (s.charAt(0) == '$') { // read Variable
				next_punct = (getGroupIndexOf(s, punct) > -1) ? getGroupIndexOf(
						s, punct) : s.length();
				next_variable = (s.indexOf("$", 1) > -1) ? s.indexOf("$", 1)
						: s.length(); // avoid finding the recent one
				next_rightBrace = (s.indexOf("}") > -1) ? s.indexOf("}") : s
						.length();

				if (next_punct <= next_variable) {
					if (next_punct <= next_rightBrace) { // next_punct wins
															// $VARIABLE
						switch (s.substring(1, next_punct)) {
						case "nbspace":
							output += "&#x00A0;";
							break;
						default:
							output += "<fo:retrieve-number reference-name=\""
									+ s.substring(1, next_punct) + "\"/>"; // remove
																			// "$"
						}
						s = s.substring(next_punct);
					} else { // next_rightBrace wins; ${VARIABLE}
						switch (s.substring(2, next_rightBrace)) {
						case "nbspace":
							output += "&#x00A0;";
							break;
						default:
							output += "<fo:retrieve-number reference-name=\""
									+ s.substring(2, next_rightBrace) + "\"/>"; // remove
																				// "${"
						}
						s = s.substring(next_rightBrace + 1); // remove }
					}
				} else {
					if (next_variable <= next_rightBrace) { // next_variable
															// wins;
															// $VARIABLE$VARIABLE
						switch (s.substring(1, next_variable)) {
						case "nbspace":
							output += "&#x00A0;";
							break;
						// case ... // Add other exceptions
						default:
							output += "<fo:retrieve-number reference-name=\""
									+ s.substring(1, next_variable) + "\"/>"; // remove
																				// "$"
						}
						s = s.substring(next_variable);
					} else { // next_rightBrace wins
						switch (s.substring(2, next_rightBrace)) {
						case "nbspace":
							output += "&#x00A0;";
							break;
						default:
							output += "<fo:retrieve-number reference-name=\""
									+ s.substring(2, next_rightBrace) + "\"/>"; // remove
																				// "${"
						}
						s = s.substring(next_rightBrace + 1); // remove }
					}
				}

			} else { // read String
				if (s.indexOf("$") > -1) {
					output += s.substring(0, s.indexOf("$"));
					s = s.substring(s.indexOf("$"));
				} else { // no variables at all
					output += s;
					s = "";
				}
			}
		}
		return output;
	}

	/*
	 * Xml fuer MappingGroup, kein Xsl beschreibt alle Mapping(Zuordnungen) und
	 * Formate.
	 * 
	 * @return: dom4j-Document-Type
	 */
	public Document getXmlDoc() {
		Document doc = DocumentHelper.createDocument();

		// <pagemasters></pagemasters>
		// root.add(pageMasterGroup.getXmlDoc().getRootElement());

		Element mapping_root = doc.addElement("mappings");

		int i = 0;
		for (Mapping st : mappingList) {
			i++;

			Element e = mapping_root.addElement("mapping");

			// id
			Element id = e.addElement("id");
			id.setText(i + "");

			// name
			Element name = e.addElement("name");
			name.setText(st.getName());

			// active
			Element active = e.addElement("active");
			active.setText(st.getActive() + "");

			Element formatEl = e.addElement("format");
			Format format = st.getFormat();

			if (format != null)
				formatEl.setText(format.getName());

			Element select = e.addElement("select");
			select.setText(st.getSelect());

			// xPath
			Element xPath = e.addElement("xPath");
			xPath.setText(XmlUtil.xPathAddPrefix(st.getxPath(),
					mainNamespacePrefix));
			// aus Liste auswaehlen
			for (ElementPath ep : st.getElementPaths()) {
				Element element = e.addElement("element");
				Element ePath = element.addElement("ePath");

				ePath.setText(XmlUtil.xPathAddPrefix(ep.getFullPathString(),
						mainNamespacePrefix));
				Element index = element.addElement("index");
				index.setText(ep.getCurrIndex() + "");
			}

		}

		// if (formatGroup != null) {
		// root.add(formatGroup.getXmlDoc().getRootElement());
		// }

		return doc;
	}

	public Document getXslDoc() {
		return getXslDocWithFile(Constants.BASE_XSLT);
	}

	/*
	 * Style zum Xsl, Fuer Xml->Fo Transformation
	 * 
	 * @return: dom4j-Document-Type
	 */
	public Document getXslDocWithFile(String xslName) {
		int xslType = 0;
		if (xslName != null && xslName.equals(Constants.FOOTNOTE_REF_XSLT)) {
			xslType = 1;
		}

		SAXReader reader = new SAXReader();
		Document xslDoc = null;
		try {
			if (xslType == 0) {
				xslDoc = reader.read(this.getClass().getResourceAsStream(
						Constants.BASE_XSLT));
			} else {
				// xslDoc = reader.read(this.getClass().getResourceAsStream(
				// Constants.FOOTNOTE_REF_XSLT));
				xslDoc = XmlUtil.createBaseInnerLinkXsl();
			}
		} catch (DocumentException e1) {
			MessageDialog.openError(
					null,
					"",
					GuiMessages.Stileditor_Error_XSLErrorReading + ": "
							+ e1.getMessage());
			e1.printStackTrace();
		}

		Element xslRoot = xslDoc.getRootElement();

		if (xslType == 1) {
			// xsl:tempalte from innerlink group
			RuntimeUtil rt = RuntimeUtil.getInstance();
			PrintProject pProject = rt.getCurrentPrintProject();
			InnerLinkGroup innerLinkGroup = pProject.getInnerLinkGroup();

			if (innerLinkGroup != null) {
				InnerLink innerLink;
				Document projectContentDoc;
				try {
					projectContentDoc = DocumentHelper.parseText(rt
							.getContentText(pProject));
					String templateStr = "";
					for (BaseItem bi : innerLinkGroup.getItems()) {
						innerLink = (InnerLink) bi;
						templateStr += innerLink.addXslTemplates(xslRoot,
								projectContentDoc.getRootElement());
					}
					if (!templateStr.isEmpty()) {
						System.out.println(templateStr);
					}
				} catch (DocumentException e) {
					e.printStackTrace();
				}
			}

			/*
			 * root = doc.getRootElement().addElement("xsl:template");
			 * root.addAttribute("match",
			 * "ref[@type='endnote' or @type='footnote' or @type='makrokommentar']"
			 * );
			 * 
			 * // <xsl:variable name="nodetype" select="@type" /> { Element e =
			 * root.addElement("xsl:variable"); e.addAttribute("name",
			 * "nodetype"); e.addAttribute("select", "@type"); }
			 * 
			 * // <xsl:variable name="nodeid" select="@target" /> { Element e =
			 * root.addElement("xsl:variable"); e.addAttribute("name",
			 * "nodeid"); e.addAttribute("select", "@target"); }
			 */
		}

		if (mainNamespacePrefix != null && mainNamespaceUri != null
				&& !mainNamespacePrefix.equals("")
				&& !mainNamespaceUri.equals("")) {
			QName qName = new QName("xmlns:" + mainNamespacePrefix);
			xslRoot.addAttribute(qName, mainNamespaceUri);
		}

		/*
		 * Write one <xsl:variable>-entry per reference system
		 */
		Document document = null;

		ReferencingSystemGroup rg = null;

		PrintProject pProject = RuntimeUtil.getInstance()
				.getCurrentPrintProject();
		if (pProject != null) {
			rg = pProject.getReferencingSystemGroup();
		}
		if (rg != null && rg.getItems() != null) {
			for (AbstractBaseItem ritem : rg.getItems()) {
				Element xslvar = xslDoc.getRootElement().addElement(
						"xsl:variable");
				xslvar.addAttribute("name", ritem.getValueOf("name"));
				try {
					String test = getRSFOText(ritem.getValueOf("schema"));
					document = DocumentHelper
							.parseText("<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\">"
									+ test + "</fo:root>");
				} catch (DocumentException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				for (int i = 0, size = document.getRootElement().nodeCount(); i < size; i++) {
					Node newNode = (Node) document.getRootElement().node(i)
							.clone();
					xslvar.add(newNode);
				}
			}
		}

		/*
		 * Replace "setupFields"
		 */
		Element template = null;

		// find Element <xsl:template name="setupFields">
		for (Object obj : xslRoot.selectNodes("xsl:template").toArray()) {
			Element e = (Element) obj;
			Attribute a = e.attribute("name");
			if (a != null && a.getText().equalsIgnoreCase("setupFields")) {
				template = e;
				break;
			}
		}

		if (template == null)
			return xslDoc;

		// Add predefined counters
		// Element fodecl = template.addElement("fo:declarations");
		Element fonumber = template.addElement("fo:number");
		fonumber.addAttribute("name", "linenumber");
		fonumber.addAttribute("layout-level", "line");

		fonumber = template.addElement("fo:number");
		fonumber.addAttribute("reference-name", "columnnumber");
		fonumber.addAttribute("layout-level", "column");

		fonumber = template.addElement("fo:number");
		fonumber.addAttribute("reference-name", "pagenumber");
		fonumber.addAttribute("layout-level", "page");

		// Add user-defined counters
		ReferenceFieldGroup rf = null;
		if (pProject != null) {
			rf = pProject.getReferenceFieldGroup();
		}
		if (rf != null && rf.getItems() != null) {
			for (AbstractBaseItem ritem : rf.getItems()) {
				fonumber = template.addElement("fop:number");
				fonumber.addAttribute("reference-name",
						ritem.getValueOf("name"));
				if (!ritem.getValueOf("content-select").equals("1")) { // not
																		// for
																		// typographic
																		// elements
					fonumber.addAttribute("layout-level", "none");
					if (ritem.getValueOf("counter-select").equals("1")) // continuous
																		// counting
						fonumber.addAttribute("initial-value",
								ritem.getValueOf("counter-startValue"));
					else
						// counting based on attribute value
						fonumber.addAttribute("initial-value",
								"@" + ritem.getValueOf("counter-attribute"));
				} else
					fonumber.addAttribute("layout-level",
							ritem.getValueOf("content-value-typo"));

				if (ritem.getValueOf("reset-select").equals("1")) // reset at
																	// another
																	// field
					fonumber.addAttribute("reset-level",
							ritem.getValueOf("reset-name"));
				else if (ritem.getValueOf("reset-select").equals("2")) // reset
																		// based
																		// on
																		// XPath
					fonumber.addAttribute("reset-level",
							ritem.getValueOf("reset-xPath"));
			}
		}

		/*
		 * Add reference rules
		 */
		if (rg != null && rg.getItems() != null) {
			for (AbstractBaseItem ritem : rg.getItems()) {
				if (!ritem.getValueOf("exceptions").isEmpty()) {
					Element ref_rule = template
							.addElement("fop:reference-rule");
					ref_rule.addAttribute("id", ritem.getValueOf("id"));
					try {
						document = DocumentHelper.parseText(ritem
								.getValueOf("exceptions"));
					} catch (DocumentException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					ref_rule.appendAttributes(document.getRootElement());
				}
			}
		}

		// find Element <xsl:template name="setupPagemasters">
		template = null;
		for (Object obj : xslRoot.selectNodes("xsl:template").toArray()) {
			Element e = (Element) obj;
			Attribute a = e.attribute("name");
			if (a != null && a.getText().equalsIgnoreCase("setupPagemasters")) {
				template = e;
				break;
			}
		}

		if (template == null)
			return xslDoc;

		// setupPagemasters
		Element layout_master_set = template.addElement("fo:layout-master-set");

		PageMasterGroup pmg = null;
		if (pProject != null)
			pmg = pProject.getPageMasterGroup();  
		
		pmg=null; //TODO: wegen fehlende Update von 22.12.2013 muss die variable vorläufig auf null setzen. YG

		if (pmg != null && pmg.getItems() != null) {
			for (AbstractBaseItem pmitem : pmg.getItems()) {
				String name = pmitem.getValueOf("name");
				String pageWidth = pmitem.getValueOf("page-layout-width");
				String pageHeight = pmitem.getValueOf("page-layout-height");
				String pageMarginTop = pmitem
						.getValueOf("page-layout-margin-top");
				String pageMarginBottom = pmitem
						.getValueOf("page-layout-margin-bottom");
				String pageMarginLeft = pmitem
						.getValueOf("page-layout-margin-left");
				String pageMarginRight = pmitem
						.getValueOf("page-layout-margin-right");
				String pageDoublesided = pmitem
						.getValueOf("page-layout-doublesided");

				// setupPagemasters
				//Element layout_master_set = template
				//		.addElement("fo:layout-master-set");

				{
					// <fo:simple-page-master master-name="odd"
					Element simple_page_master = layout_master_set
							.addElement("fo:simple-page-master");
					// master-name="odd" margin-top="2cm" margin-bottom="3cm"
					// margin-left="2cm" margin-right="2cm"
					// <fo:region-body region-name="xsl-region-body"
					// background-color="red" />
					simple_page_master.addAttribute("master-name", name + "-odd");
					simple_page_master.addAttribute("page-height", pageHeight);
					simple_page_master.addAttribute("page-width", pageWidth);
					simple_page_master
							.addAttribute("margin-top", pageMarginTop);
					simple_page_master.addAttribute("margin-bottom",
							pageMarginBottom);
					simple_page_master.addAttribute("margin-left",
							pageMarginLeft);
					simple_page_master.addAttribute("margin-right",
							pageMarginRight);
					Element region_body = simple_page_master
							.addElement("fo:region-body");
					region_body.addAttribute("region-name", "xsl-region-body");
					Element region_before = simple_page_master
							.addElement("fo:region-before");
					region_before.addAttribute("region-name", "xsl-region-before");
					Element region_after = simple_page_master
							.addElement("fo:region-after");
					region_after.addAttribute("region-name", "xsl-region-after");
				}

				{
					if (pageDoublesided.equalsIgnoreCase("true")) { //double-sided printing
						
					// <fo:simple-page-master master-name="even"
					Element simple_page_master = layout_master_set
							.addElement("fo:simple-page-master");
					simple_page_master.addAttribute("master-name", name + "-even");
					simple_page_master.addAttribute("page-height", pageHeight);
					simple_page_master.addAttribute("page-width", pageWidth);
					simple_page_master.addAttribute("margin-top", pageMarginTop);
					simple_page_master.addAttribute("margin-bottom", pageMarginBottom);
					
					simple_page_master.addAttribute("margin-left", pageMarginRight);
					simple_page_master.addAttribute("margin-right", pageMarginLeft);
					Element region_body = simple_page_master
							.addElement("fo:region-body");
					region_body.addAttribute("region-name", "xsl-region-body");
					Element region_before = simple_page_master.addElement("fo:region-before");
					region_before.addAttribute("region-name", "xsl-region-before");
					Element region_after = simple_page_master.addElement("fo:region-after");
					region_after.addAttribute("region-name", "xsl-region-after");
					
					//region_body.addAttribute("background-color", "blue");
					}
				}
			}
				
			/*
			 * Define page-sequence-master 
			 */
			
			if (pmg != null && pmg.getItems() != null) {
				for (AbstractBaseItem pmitem : pmg.getItems()) {
					String name = pmitem.getValueOf("name");
					Element page_sequence_master = layout_master_set
							.addElement("fo:page-sequence-master");
					page_sequence_master.addAttribute("master-name", name);

				/*
				 * For even pages use the page-layout "even". This is of course
				 * only interesting for double-sided printing
				 */
				//String chkpms = RuntimeUtil.getInstance().getCurrentPrintProject().getFormatGroup().getStandardFormat().getAttribute("pagemaster");
				//PageMaster chkpm = (PageMaster) RuntimeUtil.getInstance().getCurrentPrintProject().getPageMasterGroup().getItem(chkpms);
				if (pmitem.getValueOf("page-layout-doublesided").equalsIgnoreCase("true")) { //double-sided printing
					Element repeatable_page_master_alternatives = page_sequence_master
							.addElement("fo:repeatable-page-master-alternatives");
					Element conditional_page_master_reference = repeatable_page_master_alternatives
							.addElement("fo:conditional-page-master-reference");
					conditional_page_master_reference.addAttribute("master-reference", 
							name + "-odd");
					conditional_page_master_reference
						.addAttribute("odd-or-even", "odd");
					
					Element conditional_page_master_reference2 = repeatable_page_master_alternatives
							.addElement("fo:conditional-page-master-reference");
					conditional_page_master_reference2.addAttribute("master-reference",
							name + "-even");
					conditional_page_master_reference2.addAttribute("odd-or-even", "even");
				} else {
					Element repeatable_page_master = page_sequence_master
							.addElement("fo:repeatable-page-master-reference");
					repeatable_page_master.addAttribute("master-reference", name + "-odd");
				}
			}
			}
			
			// find Element <xsl:template name="setupPagemasters">
			template = null;
			for (Object obj : xslRoot.selectNodes("xsl:template").toArray()) {
				Element e = (Element) obj;
				Attribute a = e.attribute("name");
				if (a != null
						&& a.getText().equalsIgnoreCase("setupHeaderFooter")) {
					template = e;
					break;
				}
			}

			if (template == null)
				return xslDoc;

			
			
			/*
			 * Add region for page head and foot of the standard pagemaster
			 */
			pmg = null;
			if (pProject != null)
				pmg = pProject.getPageMasterGroup();

			if (pmg != null && pmg.getItems() != null) {
				for (AbstractBaseItem pmitem : pmg.getItems()) {
					if (pmitem.getValueOf("name").equals(RuntimeUtil.getInstance().getCurrentPrintProject()
							.getFormatGroup().getStandardFormat().getAttribute("pagemaster"))) {
						Element ops1 = template.addElement("xsl:value-of");
						ops1.addAttribute("select", "$openPageSequence1");
						ops1.addAttribute("disable-output-escaping", "yes");
				        Element mr = template.addElement("xsl:value-of");
				        mr.addAttribute("select", "string('" + pmitem.getValueOf("name") +"')" );
				        Element ops2 = template.addElement("xsl:value-of");
				        ops2.addAttribute("select", "$openPageSequence2");
				        ops2.addAttribute("disable-output-escaping", "yes");
						setFOStatic((PageMaster) pmitem, template);
					}
				}
			}
		}
		

		/*
		 * Write one <xsl:template>-entry per mapping
		 */
		templateCounter = 0;
		for (Mapping mapping : mappingList) {
			if (!mapping.getActive() && xslType != 1)
				continue;

			Format format = mapping.getFormat();

			// xpathText oder aus Elementbaum
			if (mapping.getSelect().equals("0")) {
				xslAddFoElement(xslType, xslRoot, mapping.getxPath(), format);
			} else {
				for (ElementPath ep : mapping.getElementPaths()) {
					xslAddFoElement(xslType, xslRoot, ep.getFullPathString(),
							format);
				}
			}
			templateCounter++;
		}

		if (xslType == 1 && xslRoot.nodeCount() < 3)
			return null;

		// xsltAddDefaultTemplate(root); //*-Template rausschreiben

		// doc = pageMaster.getXslDoc(doc);

		if (formatGroup != null & xslType != 1)
			xslDoc = formatGroup.getXslDoc(xslDoc);

		return xslDoc;
	}

	@Override
	public boolean hasElement(String name) {
		if (getMappingByName(name) != null)
			return true;
		return false;
	}

	public MappingGroup objClone() {
		MappingGroup newMp = (MappingGroup) FileUtil.objClone(this);
		return newMp;
	}
	/*
	public boolean read(InputStream in) {
		SAXReader saxReader = new SAXReader();
		saxReader.setEncoding("utf-8");
		Document doc;
		try {
			doc = saxReader.read(in);
			if (readXmlDoc(doc, false, null)) {
				return true;
			}
		} catch (DocumentException e) {
			logger.error(e);
			e.printStackTrace();
		}

		return false;
	} */

	/*
	 * private void xsltAddDefaultTemplate(Element root) { Element template =
	 * root.addElement("xsl:template"); template.addAttribute("match", "*");
	 * 
	 * Element fo_block = template.addElement("fo:block");
	 * fo_block.addAttribute("xsl:use-attribute-sets", "Standard");
	 * 
	 * Element value_of = fo_block.addElement("xsl:value-of");
	 * value_of.addAttribute("select", "."); }
	 */

	//public boolean readXmlDoc(Document doc, boolean withWizard,
	//	IObserverControl observer) {
	//return readXmlDoc(doc, null, withWizard, observer);
	//}

	/**
	 * 
	 * @param doc
	 * @param filePath
	 * @param withWizard
	 * @param observer
	 * @return
	 */
	public boolean readXmlDoc(Document doc) {
		Element root = doc.getRootElement();

		// TODO prüfen, ob xml kompatible ist, mit xml-schema
		{
			if (root.selectSingleNode("mappings") == null) {
				MessageDialog.openError(null, null,
						GuiMessages.Stileditor_Error_XML_Not_Compatible);
				return false;
			}
		}

		// PageMaster aus mappingGroup.xml einlesen
		// TODO: Add correct page master handling
		/*
		 * Node pageMastersNode = root.selectSingleNode("pagemasters"); if
		 * (pageMasterGroup == null) { pageMasterGroup = new PageMasterGroup();
		 * setPageMasterGroup(pageMasterGroup); }
		 */

		/*
		 * PageMasterGroup newPageMasterGroup =
		 * PageMasterGroup.readDocNode(pageMastersNode);
		 * 
		 * for (Object ob : root.selectSingleNode("pagemasters")
		 * .selectNodes("pagemaster").toArray()) { Node node = (Node) ob;
		 * 
		 * PageMaster pageMaster = new PageMaster();
		 * //pageMaster.setName(node.selectSingleNode
		 * ("page-layout-name").getText());
		 * 
		 * newPageMasterGroup.add(pageMaster);
		 * 
		 * }
		 */

		Node formatsNode = root.selectSingleNode("formats");

		// Formate aus mappingGroup.xml einlesen
		if (formatGroup == null) {
			formatGroup = new FormatGroup();
			setFormatGroup(formatGroup);
		}
		FormatGroup newFormatGroup = FormatGroup.readDocNode(formatsNode);

		MappingGroup newMappingGroup = new MappingGroup();
		newMappingGroup.setFormatGroup(newFormatGroup);
		
		String formatName = null;
		for (Object ob : root.selectSingleNode("mappings")
				.selectNodes("mapping").toArray()) {
			Node node = (Node) ob;

			Mapping mapping = new Mapping();
			mapping.setName(node.selectSingleNode("name").getText());
			mapping.setActive(node.selectSingleNode("active").getText()
					.equals("true") ? true : false);
			formatName = node.selectSingleNode("format").getText()
					.replaceAll("_OOO_", " ");

			if (newFormatGroup != null) {
				Format format = newFormatGroup.getFormatByName(formatName);

				if (format != null)
					mapping.setFormat(format);
			}

			mapping.setxPath(node.selectSingleNode("xPath").getText());
			mapping.setSelect(node.selectSingleNode("select").getText());

			for (Object o : node.selectNodes("element")) {
				Node n = (Node) o;
				Node ePath = n.selectSingleNode("ePath");
				Node index = n.selectSingleNode("index");

				ElementPath ep = string2ElementPath(ePath.getText(),
						index.getText());//was ist mit namespace?

				mapping.addElementPath(ep);
			}
			newMappingGroup.add(mapping);
		}

		//if (withWizard) {
		//	ImportSetupViewer impSetup = new ImportSetupViewer(this,
		//			newMappingGroup);
		//	impSetup.registerObserver(observer);
		//		impSetup.Open();
		//	} else {
			// if read mappingGroup.xml
			formatGroup = newFormatGroup;
			mappingList = newMappingGroup.getList();
			// pageMasterGroup = newPageMasterGroup;
			//	}
		return true;
	}

	/*
	 * Style-Xml einlesen eine List von Style wird erzeugt keine detaile
	 * Information von Format, nur Format-Name
	
	public void readXmlFile(String filePath, boolean withWizard,
			IObserverControl observer) {

		SAXReader reader = new SAXReader();
		File file = new File(filePath);
		Document doc = null;
		if (file.exists()) {
			try {
				doc = reader.read(file);
			} catch (DocumentException e) {
				e.printStackTrace();
			}
		} else {
			logger.error(filePath + " existiert nicht."); //$NON-NLS-N$
		}

		if (doc == null) {
			logger.error("Mapping xml ist leer."); //$NON-NLS-N$
			return;
		}

		readXmlDoc(doc, filePath, withWizard, observer);

	} */

	public void remove(Mapping mp) {
		this.mappingList.remove(mp);
	}

	/*
	 * Speichern als Xml
	
	public boolean saveToXml(String filePath) {
		File file = new File(filePath);
		Document doc = getXmlDoc();
		try {
			OutputFormat of = new OutputFormat();
			of.setIndent(true);
			of.setNewlines(true);
			Writer writer = new OutputStreamWriter(new FileOutputStream(file),
					"UTF-8");
			XMLWriter xmlWriter = new XMLWriter(writer, of);
			xmlWriter.write(doc);
			xmlWriter.close();
			return true;
		} catch (IOException e) {
			System.out.println(e.getMessage());
			return false;
		}
	} */

	private void setAttrVal(ElementPathNode epn, String epStr) {
		Pattern p = Pattern.compile("\\[.*\\]");
		Matcher m = p.matcher(epStr);

		while (m.find()) {
			String attrValStr = epStr.substring(m.start() + 1, m.end() - 1);

			// Bsp:<ePath>//TEI:hi[@rend='bold' or @rend='italic']</ePath>
			// TODO: Muss noch getestet und verbesser werden
			String[] attrValArr = attrValStr.split(" or @");
			for (String str : attrValArr) {
				str = str.trim();
				str = str.replace("@", "");
				str = str.replace("\'", "");
				String[] strArr = str.split("=");
				if (strArr.length == 2) {
					epn.addValue(strArr[0].trim(), strArr[1].trim());
				}
			}
		}
	}

	/*
	 * zugeordnete Formate
	 */
	public void setFormatGroup(FormatGroup formatGroup) {
		this.formatGroup = formatGroup;
		for (Mapping mp : mappingList) {
			Format f = formatGroup.getFormatByName(mp.getFormatName());
			mp.setFormat(f);
		}
	}
/*
	public void setPageMasterGroup(PageMasterGroup pageMasterGroup) {
		this.pageMasterGroup = pageMasterGroup;

	}

	// andere Werte fuer Seitengroessen....usw.
	public void setPageMaster(PageMaster pageMaster) {
		this.pageMaster = pageMaster;
	}*/

	public void setMainNamespacePrefix(String mainNamespacePrefix) {
		this.mainNamespacePrefix = mainNamespacePrefix;
	}

	public void setMainNamespaceUri(String mainNamespaceUri) {
		this.mainNamespaceUri = mainNamespaceUri;
	}

	public void setMappings(ArrayList<Mapping> list) {
		mappingList = list;
	}

	/*
	 * String, die inm Xml stehen, in ElementPath zu transformieren
	 */
	private ElementPath string2ElementPath(String s, String indexStr) {
		int currNodeIndex = Integer.parseInt(indexStr);

		s = s.replaceAll("//", "/");

		String[] nodeStr = s.split("/");
		ElementPathNode parent = null;
		ElementPath ep = new ElementPath();
		int i = 0;
		for (String str : nodeStr) {
			if (str.equals(""))
				continue;

			// prefix entfernen
			str = str.replaceAll(mainNamespacePrefix + ":", "");

			if (str.matches("\\w*:\\w*")) {
				String err = GuiMessages.Stileditor_Error_Unknown_NamespacePrefix
						+ ": " + str;
				MessageDialog.openInformation(null, "", err);
				logger.error(err);
			}

			// String ohne Attribute-Werte
			ElementPathNode epn = new ElementPathNode(new PElement(str
					.replaceAll("\\[.*\\]", "").trim()));

			// Attribut Werte definieren
			setAttrVal(epn, str);

			if (currNodeIndex == i)
				ep.setcurrPathNode(epn);

			ep.addNode(parent, epn);

			parent = epn;

			i++;
		}
		return ep;
	}
	
	private void setFOStatic (PageMaster pmitem, Element page_sequence) {
	 	//String name = pmitem.getValueOf("name");
		String lehead = pmitem.getValueOf("page-layout-lehead");
		String cehead = pmitem.getValueOf("page-layout-cehead");
		String rehead = pmitem.getValueOf("page-layout-rehead");
		String lohead = pmitem.getValueOf("page-layout-lohead");
		String cohead = pmitem.getValueOf("page-layout-cohead");
		String rohead = pmitem.getValueOf("page-layout-rohead");
		String lefoot = pmitem.getValueOf("page-layout-lefoot");
		String cefoot = pmitem.getValueOf("page-layout-cefoot");
		String refoot = pmitem.getValueOf("page-layout-refoot");
		String lofoot = pmitem.getValueOf("page-layout-lofoot");
		String cofoot = pmitem.getValueOf("page-layout-cofoot");
		String rofoot = pmitem.getValueOf("page-layout-rofoot");
		String pageDoublesided = pmitem.getValueOf("page-layout-doublesided");
		
		/*
		 * Add fo:page-sequence
		 */
		
		//Element page_sequence = root.addElement("fo:page-sequence");
		//page_sequence.addAttribute("master-reference", name);
		
		// header on odd pages
		Element fostatic = page_sequence.addElement("fo:static");
		fostatic.addAttribute("flow-name", "xsl-region-before");
		Element fohead = fostatic.addElement("fo:block");
		
		if (!lohead.isEmpty()) {
			Element folohead = fohead.addElement("fo:inline");
			folohead.addAttribute("text-align", "start");
			folohead.addText(lohead);
		}
		
		if (!cohead.isEmpty()) {
			Element focohead = fohead.addElement("fo:inline");
			focohead.addAttribute("text-align", "center");
			focohead.addText(cohead);
		}
		
		if (!rohead.isEmpty()) {
			Element forohead = fohead.addElement("fo:inline");
			forohead.addAttribute("text-align", "end");
			forohead.addText(rohead);
		}
		
		// footer on odd pages
		fostatic = page_sequence.addElement("fo:static");;
		fostatic.addAttribute("flow-name","xsl-region-after");
		
		Element fofoot = fostatic.addElement("fo:block");
		if (!lofoot.isEmpty()) {
			Element folofoot = fofoot.addElement("fo:inline");
			folofoot.addAttribute("text-align", "start");
			folofoot.addText(lofoot);
		}
		
		if (!cofoot.isEmpty()) {
			Element focofoot = fofoot.addElement("fo:inline");
			focofoot.addAttribute("text-align", "center");
			focofoot.addText(cofoot);
		}
		
		if (!rofoot.isEmpty()) {
			Element forofoot = fofoot.addElement("fo:inline");
			forofoot.addAttribute("text-align", "end");
			forofoot.addText(rofoot);
		}
	
		
		if (pageDoublesided == "true") {
			fostatic = page_sequence.addElement("fo:static");
			fostatic.addAttribute("flow-name", "xsl-region-before");
			fohead = fostatic.addElement("fo:block");
			
			if (!lehead.isEmpty()) {
				Element folehead = fohead.addElement("fo:inline");
				folehead.addAttribute("text-align", "start");
				folehead.addText(lehead);
			}
			
			if (!cehead.isEmpty()) {
				Element focehead = fohead.addElement("fo:inline");
				focehead.addAttribute("text-align", "center");
				focehead.addText(cehead);
			}
			
			if (!rehead.isEmpty()) {	
				Element forehead = fohead.addElement("fo:inline");
				forehead.addAttribute("text-align", "end");
				forehead.addText(rehead);
			}
			
			// footer	
			fostatic = page_sequence.addElement("fo:static");;
			fostatic.addAttribute("flow-name","xsl-region-after");
			
			fofoot = fostatic.addElement("fo:block");
			if (!lefoot.isEmpty()) {
				Element folefoot = fofoot.addElement("fo:inline");
				folefoot.addAttribute("text-align", "start");
				folefoot.addText(lefoot);
			}
			
			if (!cefoot.isEmpty()) {
				Element focefoot = fofoot.addElement("fo:inline");
				focefoot.addAttribute("text-align", "center");
				focefoot.addText(cefoot);
			}
			
			if (!refoot.isEmpty()) {
				Element forefoot = fofoot.addElement("fo:inline");
				forefoot.addAttribute("text-align", "end");
				forefoot.addText(refoot);
			}
		}
	}
	

	/*
	 * Xml Elemente und zugeordnete Format als Fo-Block in Xsl schreiben
	 */
	private void xslAddFoElement(int xslType, Element root, String nodePath,
			Format format) {

		String formatName;
		if (format == null) {
			return;
		} else {
			formatName = format.getFormatedName();
		}

		if (formatName == null)
			formatName = "";

		nodePath = XmlUtil.xPathAddPrefix(nodePath, mainNamespacePrefix);
		Element template;

		// für fn_ref.xsl
		if (xslType == 1) {
			if (!format.getFoCategory().equals("footnote"))
				return;

			/*
			 * <xsl:for-each
			 * select="//note[@type=$nodetype and @xml:id=$nodeid]">
			 * <xsl:copy-of select="." /> </xsl:for-each>
			 */
			{
				Element e = root.addElement("xsl:for-each");
				nodePath = nodePath.trim();
				if (nodePath.endsWith("]")) {
					nodePath = nodePath.substring(0, nodePath.length() - 1);
					nodePath += " and @xml:id=$nodeid]";
				} else {
					nodePath += "[@xml:id=$nodeid]";
				}

				e.addAttribute("select", nodePath);
				Element e1 = e.addElement("xsl:copy-of");
				e1.addAttribute("select", ".");
				Element temp = e.addElement("TTTT");
				temp.addAttribute("tttt", "tttt");
			}

			return;
		}

		// folgend für base_xsl
		template = root.addElement("xsl:template");
		template.addAttribute("match", nodePath);
		template.addAttribute("priority", this.mappingList.size()
				- templateCounter + "");

		if (format.getType().equals("ignore"))
			return;

		// block, inline oder footnote
		// footnote
		if (format.getFoCategory().equals("footnote")) {
			String fn_prefix = format.getFootnoteAttribute("fn-prefix");
			String fn_postfix = format.getFootnoteAttribute("fn-postfix");
			String fn_reset = format.getFootnoteAttribute("fn-reset");
			String fn_type = format.getFootnoteAttribute("fn-type");
			String fn_baseline_shift = format
					.getFootnoteAttribute("fn-baseline-shift");
			String fn_reference = format.getFootnoteAttribute("fn-refSystem");
			
			// TODO numberingstyle sollte eigene Tag haben
			String fn_numbering = "";
			if (!format.getFootnoteAttribute("fn-numberingstyle").isEmpty())
				fn_numbering = format.getFootnoteAttribute("fn-numberingstyle")
						.substring(0, 1);
			String fn_number_text = "";
			if (!fn_numbering.isEmpty())
				fn_number_text = fn_numbering + fn_postfix;

			Element fo = template.addElement("fo:footnote");
			/*
			 * Notlösung für Sperrung
			 */
			if (!format.getAttribute("letter-spacing").equalsIgnoreCase(
					"normal")
					&& !format.getAttribute("letter-spacing").equalsIgnoreCase(
							"none")
					&& !format.getAttribute("letter-spacing").equalsIgnoreCase(
							"")) { // Default value
				// fo.addAttribute("white-space-treatment", "preserve");
				fo.addAttribute("white-space-collapse", "false");
			}

			// footnote id nur bei xml-print engine
			if (Configuration.getInstance().getEngineName()
					.equalsIgnoreCase("XML-Print")) {
				fo.addAttribute("place", format.getId());
				// fo.addAttribute("fn-id", "1");
				if (fn_type.equalsIgnoreCase("Endnote")) {
					fo.addAttribute("fn-type", "endnote");
				}
			}
			Element xslnumber = null;
			Element fonumber = fo.addElement("fo:inline");
			if (!fn_number_text.isEmpty()) { // no predefined reference system
												// //TODO: use correct
												// if-condition
				fonumber.addAttribute("font-size", "70%");
				fonumber.addAttribute("baseline-shift", "super");
				fonumber.addText(fn_prefix);
				xslnumber = fonumber.addElement("xsl:number");
				xslnumber.addAttribute("level", "any");
				int i1 = nodePath.lastIndexOf("]");
				if (i1 >= 0) {
					String nodePath2 = nodePath.substring(0, i1)
							+ " and following-sibling::*[@tttt='tttt']]";
					xslnumber.addAttribute("count", nodePath2);
				}
				if (!fn_reset.equals("")) {
					xslnumber.addAttribute("from", fn_reset);
				}
				xslnumber.addAttribute("format", fn_number_text);
			} else { // for reference systems
				fonumber.addAttribute("font-size", "70%");
				fonumber.addAttribute("baseline-shift", "super");
				// Check, whether used referencing system has some exceptions
				String lookupID = RuntimeUtil.getInstance()
						.getCurrentPrintProject().getReferencingSystemGroup()
						.getItem(fn_reference).getValueOf("id");
				if (!RuntimeUtil.getInstance().getCurrentPrintProject()
						.getReferencingSystemGroup().getItem(fn_reference)
						.getValueOf("exceptions").isEmpty()) {
					Element userefrule = fonumber
							.addElement("fop:use-reference-rule");
					userefrule.addAttribute("id", lookupID);
					Element xsl_ct = userefrule.addElement("xsl:copy-of");
					xsl_ct.addAttribute("select", "$" + fn_reference);
				} else {
					Element xsl_ct = fonumber.addElement("xsl:copy-of");
					xsl_ct.addAttribute("select", "$" + fn_reference);
				}
			}

			Element fobody = fo.addElement("fo:footnote-body");
			Element fobodytext = fobody.addElement("fo:block");
			fobodytext.addAttribute("xsl:use-attribute-sets", formatName);
			Element fobodyreference = fobodytext.addElement("fo:inline");
			if (!fn_numbering.isEmpty()) {
				if (fn_baseline_shift.equals("super")) {
					fobodyreference.addAttribute("font-size", "70%");
				}
				fobodyreference.addAttribute("baseline-shift",
						fn_baseline_shift);
				fobodyreference.addText(fn_prefix);
				xslnumber = fobodyreference.addElement("xsl:number");
				xslnumber.addAttribute("level", "any");
				String nodePath3 = nodePath.replaceAll("/", "");
				int i2 = nodePath.lastIndexOf("]");
				if (i2 >= 0) {
					nodePath3 = nodePath.substring(0, i2)
							+ " and following-sibling::*[@tttt='tttt']]";
					xslnumber.addAttribute("count", nodePath3);
				}

				if (!fn_reset.equals("")) {
					xslnumber.addAttribute("from", fn_reset);
				}
				xslnumber.addAttribute("format", fn_number_text);
				Element xsltext = fobodyreference.addElement("xsl:text");
				xsltext.addText(" ");
			} else { // for reference systems
				if (fn_baseline_shift.equals("super")) {
					fobodyreference.addAttribute("font-size", "70%");
				}
				fobodyreference.addAttribute("baseline-shift",
						fn_baseline_shift);

				String lookupID = RuntimeUtil.getInstance()
						.getCurrentPrintProject().getReferencingSystemGroup()
						.getItem(fn_reference).getValueOf("id");
				if (!RuntimeUtil.getInstance().getCurrentPrintProject()
						.getReferencingSystemGroup().getItem(fn_reference)
						.getValueOf("exceptions").isEmpty()) {
					Element userefrule = fobodyreference
							.addElement("fop:use-reference-rule");
					userefrule.addAttribute("id", lookupID);
					Element xsl_ct = userefrule.addElement("xsl:copy-of");
					xsl_ct.addAttribute("select", "$" + fn_reference);
				} else {
					Element xsl_ct = fobodyreference.addElement("xsl:copy-of");
					xsl_ct.addAttribute("select", "$" + fn_reference);
				}
			}
			// if (xslnumber != null) {
			// fonumber.addText("@@" + nodePath);
			// }
			fobodytext.addElement("xsl:apply-templates");
		} else { // block or inline
			/*
			 * First we check, if the pagemaster was changed by the user for this format
			 * If so, we have to close the recent page sequence including fo:flow and fop:columns 
			 * and reopen it again with the new settings.
			 */
			Element fo;
			if (!format.equals(getFormatGroup().getStandardFormat()) && !format.getAttribute("pagemaster").equalsIgnoreCase(oldPM)) { 
				/*
				 * Call template "newPageSequence" and use the recent pagemaster as a parameter
				 */
				Element newPagesequence = template.addElement("xsl:call-template");
				newPagesequence.addAttribute("name", "newPageSequence");
				Element withParam = newPagesequence.addElement("xsl:with-param");
				withParam.addAttribute("name", "masterreference");
				withParam.addAttribute("select", "string('" + format.getAttribute("pagemaster") + "')");
				
				/*
				 * Look for page master and set the corresponding fo:static regions
				 */
				PrintProject pProject = RuntimeUtil.getInstance().getCurrentPrintProject();
				PageMasterGroup pmg = null;
				if (pProject != null)
					pmg = pProject.getPageMasterGroup();
				
				if (pmg != null && pmg.getItems() != null) {
					for (AbstractBaseItem pmitem : pmg.getItems()) {
						if (pmitem.getValueOf("name").equalsIgnoreCase(format.getAttribute("pagemaster")))
							setFOStatic((PageMaster) pmitem, template);
					}
				}
				
				/*
				 * Now we can add fo:flow again
				 */
				Element ops3 = template.addElement("xsl:value-of");
				ops3.addAttribute("select", "$openPageSequence3");
				ops3.addAttribute("disable-output-escaping", "yes");
				
				/*
				 * Remember pagemaster for next test
				 */
				oldPM = format.getAttribute("pagemaster");
			
				String blockInline = format.getFoCategory();
				Element fop = template.addElement("fop:columns");
				if (blockInline.equalsIgnoreCase("block")) { // sum up fo:block and fop:columns
					fop.addAttribute("xsl:use-attribute-sets", "Standard-columns" + " " +  "standard" + " " + formatName + "-columns" + " " + formatName);
					fo = fop; // for later use
				} else { // for inline just add fop:columns
					fop.addAttribute("xsl:use-attribute-sets", formatName
							+ "-columns");
					fo = fop.addElement("fo:" + blockInline);
				}
			} else {
				String blockInline = format.getFoCategory();
				if (!format.isInherit("column-count") && !format.equals(getFormatGroup().getStandardFormat())) { // information on multicolumned text
					Element fop = template.addElement("fop:columns");
					if (blockInline.equalsIgnoreCase("block")) { // sum up fo:block and fop:columns
						fop.addAttribute("xsl:use-attribute-sets", formatName + "-columns" + " " + formatName);
						fo = fop; // for later use
					} else { // for inline just add fop:columns
						fop.addAttribute("xsl:use-attribute-sets", formatName + "-columns");
						fo = fop.addElement("fo:" + blockInline);
					}
				} else { // output fo:block or fo:inline
					fo = template.addElement("fo:" + blockInline);
					fo.addAttribute("xsl:use-attribute-sets", formatName);
				}
			}
			/*
			 * Notlösung für Sperrung
			 */
			if (!format.getAttribute("letter-spacing").equalsIgnoreCase(
					"normal")
					&& !format.getAttribute("letter-spacing").equalsIgnoreCase(
							"none")
					&& !format.getAttribute("letter-spacing").equalsIgnoreCase(
							"")) { // Default value
				// fo.addAttribute("white-space-treatment", "preserve");
				fo.addAttribute("white-space-collapse", "false");
			}

			/*
			 * Check if there is a field information (counter) for this
			 * template, i.e. for this XPath expression Increase the appropriate
			 * counter, if necessary set the value according to an XML element
			 */

			ReferenceFieldGroup referenceGroup = RuntimeUtil.getInstance()
					.getCurrentPrintProject().getReferenceFieldGroup();
			for (AbstractBaseItem rf : referenceGroup.getItems()) {
				if (rf.getValueOf("content-select").equals("0")) { // only for
																	// format
																	// based
																	// fields
					if (rf.getValueOf("content-value-format").equalsIgnoreCase(
							formatName)) { // test whether both format names are
											// the same
						fo.addAttribute("number-ref-id", rf.getValueOf("name")); // add
																					// attribute
																					// to
																					// increase
																					// counter
																					// by
																					// 1
						if (rf.getValueOf("counter-select").equals("0")) { // counter
																			// based
																			// on
																			// attribute
																			// for
																			// non
																			// typographic
																			// counter
							Element attr = fo.addElement("xsl:attribute");
							attr.addAttribute("name", "number-ref-value");
							Element innerattr = attr.addElement("xsl:value-of");
							innerattr.addAttribute("select",
									"@" + rf.getValueOf("counter-attribute"));
						}
					}
				}
			}

			/*
			 * 
			 * Element value_of = fo_block.addElement("xsl:value-of");
			 * value_of.addAttribute("select", ".");
			 */
			if (!format.getAttribute("text-addition-before").isEmpty()) {
				Pattern patt = Pattern.compile("(0x[0-9a-fA-F]{4})");
				Matcher m = patt.matcher(format
						.getAttribute("text-addition-before"));
				StringBuffer sb = new StringBuffer(format.getAttribute(
						"text-addition-before").length());
				while (m.find()) {
					String text = m.group(1);
					int i = Integer.parseInt(text.substring(2), 16); // get only
																		// digits
					text = String.valueOf((char) i);
					m.appendReplacement(sb, Matcher.quoteReplacement(text));
				}
				m.appendTail(sb);

				patt = Pattern.compile("(@[a-z]*)");
				m = patt.matcher(sb.toString());
				sb = new StringBuffer(sb.toString().length());
				while (m.find()) {
					String text = m.group(1); // remember match
					m.appendReplacement(sb, Matcher.quoteReplacement("")); // Match
																			// is
																			// ignored
																			// first
					fo.addText(sb.toString());
					Element sel = fo.addElement("xsl:value-of");
					sel.addAttribute("select", text);
					sb.delete(0, sb.length() - 1); // reset Stringbuffer
				}
				m.appendTail(sb);
				fo.addText(sb.toString());
			}
			fo.addElement("xsl:apply-templates");
			if (!format.getAttribute("text-addition-after").isEmpty()) {
				Pattern patt = Pattern.compile("(0x[0-9a-fA-F]{4})");
				Matcher m = patt.matcher(format
						.getAttribute("text-addition-after"));
				StringBuffer sb = new StringBuffer(format.getAttribute(
						"text-addition-after").length());
				while (m.find()) {
					String text = m.group(1);
					int i = Integer.parseInt(text.substring(2), 16); // get only
																		// digits
					text = String.valueOf((char) i);
					m.appendReplacement(sb, Matcher.quoteReplacement(text));
				}
				m.appendTail(sb);

				patt = Pattern.compile("(@[a-z]*)");
				m = patt.matcher(sb.toString());
				sb = new StringBuffer(sb.toString().length());
				while (m.find()) {
					String text = m.group(1); // remember match
					m.appendReplacement(sb, Matcher.quoteReplacement("")); // Match
																			// is
																			// ignored
																			// first
					fo.addText(sb.toString());
					Element sel = fo.addElement("xsl:value-of");
					sel.addAttribute("select", text);
					sb.delete(0, sb.length() - 1); // reset Stringbuffer
				}
				m.appendTail(sb);
				fo.addText(sb.toString());
			}

		}
	}
}
